<style scoped lang="scss">
.container {
    position: relative;
    .canvas {
        position: absolute;
        left: 0;
        top: 0;
    }
}
</style>
<template>
    <div class="container">
        <div class="canvas"></div>
    </div>
</template>

<script setup lang="ts">
import { onMounted } from "vue";
let canvas: HTMLCanvasElement;
let ctx: CanvasRenderingContext2D;
let container: HTMLDivElement;
// 矩形
const juxing = () => {
    // 实心
    // ctx?.fillRect(100, 100, 100, 100);
    // 描边
    // ctx?.strokeRect(100, 100, 100, 100);
    // 设置矩形路径:只规划，此时并没有画
    ctx?.rect(100, 100, 100, 100);
    // 配合下边两个开始画
    // 颜色设置:在绘画之前设置颜色，会默认对之前所有绘制的路径进行处理
    ctx!.fillStyle = "#f00"; //填充色
    ctx!.strokeStyle = "#00f"; //描边颜色
    ctx!.lineWidth = 5; //线宽
    ctx?.stroke(); //描边
    ctx?.fill(); //填充
};
// 圆角矩形
const yuanjuxing = () => {
    // x,y,w,h,r:(10|[10]);([10,20]左上右下，右上左下，对角线设置);([10,20,10]左上，右上左下，右下);([10,20,30,40])
    ctx?.roundRect(10, 10, 100, 100, 50);
    ctx!.strokeStyle = "#f00";
    ctx!.lineWidth = 10;
    ctx?.stroke();
};
let x = 0;
// 直线
const line = (count: number) => {
    ctx?.moveTo(0, 0);
    ctx?.lineTo(100, 200);
    ctx?.lineTo(200, 200);
    ctx?.stroke();
    ctx?.moveTo(30, 400);
    ctx?.lineTo(40, 400);
    ctx?.stroke();

    // if (x == 200) {
    //     x - +count;
    // } else {
    //     x += count;
    // }
    // ctx.moveTo(0, 20);
    // ctx.lineTo(x, 20);
    // ctx.stroke();
};
const xuxian = () => {
    ctx.beginPath();
    ctx?.setLineDash([200]);
    ctx!.lineWidth = 100;
    // ctx!.lineCap = "round";
    ctx.lineDashOffset = 190;
    ctx?.moveTo(0, 20);
    ctx?.lineTo(200, 20);
    ctx?.stroke();
};
// 虚线横向滚动
const xuxianAnimation1 = () => {
    ctx.lineDashOffset = 200;
    const move = () => {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.beginPath();
        ctx.setLineDash([200]);
        ctx.lineWidth = 20;
        ctx.lineDashOffset--;
        ctx.moveTo(0, 30);
        ctx.lineTo(200, 30);
        ctx.stroke();
        if (ctx.lineDashOffset == -200) {
            ctx.lineDashOffset = 200;
        }
        requestAnimationFrame(move);
    };
    requestAnimationFrame(move);
};
// 虚线方形
const xuxianAnimation2 = () => {
    ctx.lineDashOffset = -10;
    const move = () => {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.beginPath();
        ctx.setLineDash([10]);
        ctx.lineWidth = 2;
        ctx.lineDashOffset++;
        ctx.moveTo(10, 10);
        ctx.lineTo(10, 200);
        ctx.lineTo(200, 200);
        ctx.lineTo(200, 10);
        ctx.lineTo(10, 10);
        ctx.stroke();
        if (ctx.lineDashOffset == 10) {
            ctx.lineDashOffset = -10;
        }
        requestAnimationFrame(move);
    };
    requestAnimationFrame(move);
};
// 圆弧
const arc = () => {
    // ctx.clearRect(0, 0, canvas.width, canvas.height);
    // ctx.beginPath();
    // ctx.arc(100, 100, 50, 0, (Math.PI * 270) / 180);
    // ctx.stroke();
    // ctx.fill();
    ctx.beginPath();
    ctx.fillStyle = "#f00";
    ctx.fillRect(100, 100, 100, 100);

    ctx.beginPath();
    ctx.moveTo(100, 100);
    ctx.arcTo(100, 200, 200, 200, 100);
    ctx.stroke();
};
// 椭圆
const tuoyuan = () => {
    ctx.beginPath();
    ctx.ellipse(100, 100, 40, 20, 0, 0, Math.PI * 2);
    ctx.stroke();
};
// 贝赛尔曲线
const beisaier = () => {
    ctx.fillStyle = "#f00";
    ctx.beginPath();
    // 起点
    ctx.arc(10, 100, 4, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath();
    // 第一个控制点
    ctx.arc(50, 200, 4, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath();
    // 第二个控制点
    ctx.arc(150, 50, 4, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath();
    // 终点
    ctx.arc(200, 100, 4, 0, Math.PI * 2);
    ctx.fill();
    // 二次贝塞尔
    ctx.beginPath();
    ctx.moveTo(10, 100);
    ctx.quadraticCurveTo(50, 200, 200, 100);
    ctx.stroke();
    // 三次贝塞尔
    ctx.beginPath();
    ctx.moveTo(10, 100);
    ctx.bezierCurveTo(50, 200, 150, 50, 200, 100);
    ctx.stroke();
};
// 文本
const text = () => {
    ctx.beginPath();
    ctx.font = "bold italic 20px sans-serif";
    ctx.fillText("周童大帅比", 20, 20);
    ctx.strokeText("周童大帅比", 40, 40);
};
// 连续图
const imageAnimation = () => {
    const img = new Image();
    img.src = "/01.png";
    img.onload = () => {
        let i = 0;
        const show = () => {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.drawImage(img, i * 400, 0, 400, 300, i, 0, 200, 200);
            i++;
            if (i == 5) {
                i = 0;
            }
        };
        show();
        setInterval(show, 100);
    };
};
// canvas编程式下载
const imageDownload = () => {
    let canvas = document.createElement("canvas");
    canvas.width = 200;
    canvas.height = 200;
    let ctx = canvas.getContext("2d");
    for (let index = 1; index < 6; index++) {
        ctx?.beginPath();
        ctx?.arc(100, 100, 20 * index, 0, Math.PI * 2);
        ctx?.stroke();
    }
    const btn = document.createElement("button");
    btn.innerText = "下载";
    btn.onclick = () => {
        let url = canvas.toDataURL();
        const a = document.createElement("a");
        a.href = url;
        a.download = "canvas图片";
        a.click();
    };
    document.body.appendChild(btn);
};
// 像素控制
const pixelControl = () => {
    const img = new Image();
    img.src = "/02.jpeg";
    img.onload = () => {
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        for (let index = 0; index < imageData.data.length; index += 4) {
            let r = imageData.data[index];
            let g = imageData.data[index + 1];
            let b = imageData.data[index + 2];
            let a = imageData.data[index + 3];
            // 1.灰度(取平均或者置为红色通道等)
            const avg = (r + g + b) / 3;
            imageData.data[index] = avg; //r
            imageData.data[index + 1] = avg; //r;
            imageData.data[index + 2] = avg; //r
            // 2.取相反色
            imageData.data[index] = 255 - r; //r
            imageData.data[index + 1] = 255 - g; //r;
            imageData.data[index + 2] = 255 - b; //r
        }
        ctx.putImageData(imageData, 0, 0);
    };
};
// 图案填充
const picFill = () => {
    const img = new Image();
    img.src = "/02.jpeg";
    img.onload = () => {
        const pattern = ctx.createPattern(img, null) as CanvasPattern;
        ctx.strokeStyle = pattern;
        ctx.arc(200, 200, 100, 0, Math.PI * 2);
        ctx.lineWidth = 5;
        ctx.stroke();
    };
};
// 图像裁剪
const picClip = () => {
    ctx.strokeRect(100, 100, 200, 200);
    ctx.beginPath();
    ctx.fillStyle = "rgb(255,0,0)";
    // 1.在中心方框中展示
    // ctx.moveTo(150, 150);
    // ctx.lineTo(150, 250);
    // ctx.lineTo(250, 250);
    // ctx.lineTo(250, 150);
    // ctx.closePath();

    // 2.显示圆环(因为路径存在顺逆差，所以触发非零环绕路径，中心区域数量为0，剪切掉)
    // ctx.arc(200, 200, 100, 0, Math.PI * 2, false);
    // ctx.arc(200, 200, 80, 0, Math.PI * 2, true);
    // ctx.clip();
    // 奇偶不管顺逆
    ctx.arc(200, 200, 100, 0, Math.PI * 2, false);
    ctx.arc(200, 200, 80, 0, Math.PI * 2, false);
    ctx.clip("evenodd");
    ctx.fillRect(100, 100, 200, 200);
};
// 图像合成
const picCompound = () => {
    ctx.beginPath();
    ctx.fillStyle = "rgb(255,0,0)";
    ctx.fillRect(100, 100, 100, 100);
    ctx.globalCompositeOperation = "destination-atop";
    ctx.beginPath();
    ctx.fillStyle = "rgb(0,255,0)";
    ctx.fillRect(150, 150, 100, 100);
    ctx.globalCompositeOperation = "source-atop";
    ctx.beginPath();
    ctx.fillStyle = "rgb(0,0,255)";
    ctx.fillRect(200, 200, 100, 100);
};
// 图像合成之刮刮乐
const guaguale = () => {
    // 1.制作底片
    const img = new Image();
    img.src = "/02.jpeg";
    img.width = canvas.width;
    img.height = canvas.height;
    img.style.userSelect = "none";
    container.appendChild(img);
    // 2.创造涂层
    ctx.beginPath();
    ctx.fillStyle = "grey";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.globalCompositeOperation = "destination-out";
    ctx.beginPath();
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.lineWidth = 20;
    // 3.鼠标移动触发合成，每次只显示重叠之外涂层，重叠处消失
    canvas.onmousedown = (e) => {
        let x = e.offsetX;
        let y = e.offsetY;
        ctx.moveTo(x, y);
        ctx.stroke();
        canvas.onmousemove = (e) => {
            ctx.lineTo(e.offsetX, e.offsetY);
            ctx.stroke();
        };
        document.onmouseup = () => {
            canvas.onmousemove = null;
            document.onmouseup = null;
        };
    };
};
// 线性渐变
const linearGradient = () => {
    const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
    gradient.addColorStop(0, "red");
    gradient.addColorStop(0.5, "yellow");
    gradient.addColorStop(1, "blue");
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, canvas.width, 300);
};
// 径向渐变
const radialGradient = () => {
    const gradient = ctx.createRadialGradient(200, 200, 50, 200, 200, 200);
    gradient.addColorStop(0, "red");
    gradient.addColorStop(1, "yellow");
    ctx.fillStyle = gradient;
    ctx.arc(200, 200, 200, 0, Math.PI * 2);
    ctx.stroke();
    ctx.fill();
};
// 锥形渐变
const zhuixingGradient = () => {
    const gradient = ctx.createConicGradient(0, 200, 200);
    gradient.addColorStop(0, "rgb(255,0,0)");
    gradient.addColorStop(0.25, "rgb(122,0,0)");
    gradient.addColorStop(0.5, "rgb(0,255,0)");
    gradient.addColorStop(0.75, "rgb(0,122,0)");
    gradient.addColorStop(1, "rgb(0,0,255)");
    ctx.fillStyle = gradient;
    ctx.arc(200, 200, 200, 0, Math.PI * 2);
    ctx.stroke();
    ctx.fill();
};
// 阴影
const shadows = () => {
    ctx.shadowBlur = 100;
    ctx.shadowColor = "yellow";
    ctx.fillStyle = "red";
    ctx.arc(200, 200, 100, 0, Math.PI * 2);
    ctx.fill();
};
// 图形变化
const picChange = () => {};
// 绘制坐标系
const xy = () => {
    const shuxianchangdu = 5;
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(canvas.width, 0);
    ctx.moveTo(0, 0);
    ctx.lineTo(-canvas.width, 0);
    // ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(0, canvas.height);
    ctx.moveTo(0, 0);
    ctx.lineTo(0, -canvas.height);
    ctx.lineWidth = 2;
    ctx.strokeStyle = "rgb(255,0,0)";
    ctx.stroke();
    ctx.beginPath();
    ctx.arc(0, 0, 5, 0, Math.PI * 2);
    ctx.fill();
    for (let index = 10; index < canvas.width; index += 10) {
        ctx.beginPath();
        // 1.绘制x轴数值线段
        ctx.moveTo(index, -shuxianchangdu);
        ctx.lineTo(index, shuxianchangdu);
        ctx.moveTo(-index, -shuxianchangdu);
        ctx.lineTo(-index, shuxianchangdu);
        // 2.绘制y轴数值线段
        ctx.moveTo(-shuxianchangdu, index);
        ctx.lineTo(shuxianchangdu, index);
        ctx.moveTo(-shuxianchangdu, -index);
        ctx.lineTo(shuxianchangdu, -index);
        ctx.stroke();
    }

    ctx.beginPath();
};
// 矩阵变化
const juzhenChange = () => {
    // 1.矩阵移动(x右移20，y下移40)
    // ctx.transform(1, 0, 0, 1, 20, 40);
    // 2.矩阵放缩(x放大到2倍，y放大到2倍)
    // ctx.transform(2, 0, 0, 2, 0, 0);
    // 3.矩阵斜切
    // ctx.transform(1, 0, Math.tan((30 * Math.PI) / 180), 1, 0, 0);
    // 4.矩阵旋转
    ctx.transform(
        Math.cos((45 * Math.PI) / 180),
        Math.sin((45 * Math.PI) / 180),
        -Math.sin((45 * Math.PI) / 180),
        Math.cos((45 * Math.PI) / 180),
        40,
        40
    );
    xy();

    ctx.strokeStyle = "blue";
    ctx.strokeRect(100, 100, 100, 100);
};
const init = () => {
    container = document.querySelector(".container") as HTMLDivElement;
    const el = document.querySelector(".canvas");
    canvas = document.createElement("canvas");

    canvas.width = 800;
    canvas.height = 800;
    // canvas.style.width = "800px";
    // canvas.style.height = "800px";
    if (!canvas.getContext) {
        //不支持canvas
    } else {
        ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
        // juxing();
        // yuanjuxing();
        // line(5);
        // xuxian();
        // xuxianAnimation1();
        // xuxianAnimation2();
        // arc();
        // tuoyuan();
        // beisaier();
        // text();
        // imageAnimation();
        // imageDownload();
        // pixelControl();
        // picFill();
        // picClip();+
        // picCompound();
        // guaguale();
        // linearGradient();
        // radialGradient();
        // zhuixingGradient();
        // shadows();
        juzhenChange();
    }
    el?.appendChild(canvas);
};
onMounted(() => {
    init();
});
</script>
